package com.example.vault.aspect;

import com.example.vault.annotation.DataSource;
import com.example.vault.config.DynamicDataSource;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 数据源切换切面
 * 根据@DataSource注解自动切换数据源
 */
@Aspect
@Component
@Order(1) // 确保在事务切面之前执行
public class DataSourceAspect {

    private static final Logger logger = LoggerFactory.getLogger(DataSourceAspect.class);

    /**
     * 切点：拦截所有标注@DataSource注解的方法
     */
    @Pointcut("@annotation(com.example.vault.annotation.DataSource) || @within(com.example.vault.annotation.DataSource)")
    public void dataSourcePointcut() {
    }

    /**
     * 环绕通知：在方法执行前后进行数据源切换
     */
    @Around("dataSourcePointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        
        // 获取方法上的@DataSource注解
        DataSource dataSource = method.getAnnotation(DataSource.class);
        
        // 如果方法上没有注解，尝试获取类上的注解
        if (dataSource == null) {
            dataSource = method.getDeclaringClass().getAnnotation(DataSource.class);
        }
        
        // 如果仍然没有注解，使用默认的主库
        DynamicDataSource.DataSourceType dataSourceType = DynamicDataSource.DataSourceType.MASTER;
        String database = "transaction";
        
        if (dataSource != null) {
            dataSourceType = dataSource.value();
            database = dataSource.database();
        }
        
        try {
            // 设置数据源类型
            DynamicDataSource.setDataSourceType(dataSourceType);
            
            logger.debug("切换到数据源: {} - {}, 方法: {}.{}", 
                database, dataSourceType.getValue(), 
                method.getDeclaringClass().getSimpleName(), 
                method.getName());
            
            // 执行目标方法
            return point.proceed();
            
        } catch (Exception e) {
            logger.error("数据源切换异常: {}", e.getMessage(), e);
            throw e;
        } finally {
            // 清理线程本地变量
            DynamicDataSource.clearDataSourceType();
            logger.debug("清理数据源上下文");
        }
    }
}